Skip to content

feat: model dual-era ChatGPT protocol selection - #3828

Open
ignaciojimenezr wants to merge 2 commits into
mainfrom
codex/chatgpt-protocol-profile
Open

feat: model dual-era ChatGPT protocol selection#3828
ignaciojimenezr wants to merge 2 commits into
mainfrom
codex/chatgpt-protocol-profile

Conversation

@ignaciojimenezr

@ignaciojimenezr ignaciojimenezr commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

What this does

Adds ChatGPT's Automatic, MCP 2025, and MCP 2026 selection behavior to the Inspector and SDK.

  • Keeps clientInfo and supportedProtocolVersions under mcpProfile.initialize.
  • Stores auto as a selection policy alongside explicit 2025 and 2026 pins.
  • 2025 uses the legacy initialize handshake.
  • 2026 uses modern discovery and never sends initialize.
  • Automatic negotiates modern first and falls back to a supported legacy version.
  • Per-server pins override the host default.
  • Concrete pins must appear in the client's advertised support list.
  • Regenerates the bundled ChatGPT profile from the backend catalog.

Related backend stack

  • MCPJam/mcpjam-backend#929: generic host-config capability modeling
  • MCPJam/mcpjam-backend#872: ChatGPT values and dual-protocol profile

Validation

  • SDK and Inspector client typechecks
  • 163 focused SDK tests
  • 20 ProtocolTab tests
  • Dual-era fixture coverage for Automatic, 2025, and 2026

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Aug 10, 2026
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@dosubot dosubot Bot added the enhancement New feature or request label Aug 10, 2026
@chelojimenez

chelojimenez commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The change adds "auto" as an explicit MCP protocol negotiation policy across SDK host profiles, canonicalization, connection setup, runtime negotiation, and inspector controls. Concrete protocol pins still require advertised-version compatibility. Automatic mode preserves configured supported versions, omits a wire-level protocol pin, and supports modern and legacy connection paths. Tests cover precedence, serialization, reconnect behavior, filtering, warnings, and dropdown persistence.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
sdk/src/host-config/canonicalize.ts (1)

888-937: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Validate stateless protocol pins against the advertised list.

The check excludes stateless pins. Therefore, this profile is accepted:

mcpProtocolVersion: "2026-07-28" with supportedProtocolVersions: ["2025-11-25"].

MCPClientManager then sends the 2026 pin while it advertises only 2025 support. Validate every concrete pin when an advertised list exists. Keep the stateful-only derivation behavior after that validation.

Add a canonicalization test for this conflicting 2026 pin.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@sdk/src/host-config/canonicalize.ts` around lines 888 - 937, Update the
cross-field validation in canonicalization to validate every concrete
mcpProtocolVersion, including stateless versions, whenever
supportedProtocolVersions or initialize.supportedProtocolVersions is present;
throw the existing conflict error when the pin is absent from the advertised
list. Preserve the current stateful-only derivation behavior for missing
advertised lists, and add a canonicalization test covering a 2026 stateless pin
conflicting with a 2025 advertised version.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@sdk/src/host-config/canonicalize.ts`:
- Around line 888-937: Update the cross-field validation in canonicalization to
validate every concrete mcpProtocolVersion, including stateless versions,
whenever supportedProtocolVersions or initialize.supportedProtocolVersions is
present; throw the existing conflict error when the pin is absent from the
advertised list. Preserve the current stateful-only derivation behavior for
missing advertised lists, and add a canonicalization test covering a 2026
stateless pin conflicting with a 2025 advertised version.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 62f7b958-05c9-425e-820c-2816c2a27af1

📥 Commits

Reviewing files that changed from the base of the PR and between 2d8d395 and 2b185fa.

⛔ Files ignored due to path filters (2)
  • sdk/src/host-compat/catalog.generated.ts is excluded by !**/*.generated.*
  • sdk/tests/__snapshots__/host-config-seed-host-template.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (22)
  • mcpjam-inspector/client/src/components/connection/ServerDetailModal.tsx
  • mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx
  • mcpjam-inspector/client/src/components/hosts/redesigned/focus/__tests__/ProtocolTab.versionDropdown.test.tsx
  • mcpjam-inspector/client/src/lib/__tests__/client-config-v2-mcp-profile.test.ts
  • mcpjam-inspector/client/src/lib/client-config-v2.ts
  • mcpjam-inspector/client/src/lib/host-config-field-schema.ts
  • sdk/src/host-config/canonicalize.ts
  • sdk/src/host-config/defaults.ts
  • sdk/src/host-config/host-connection.ts
  • sdk/src/host-config/host.ts
  • sdk/src/host-config/public-types.ts
  • sdk/src/host-config/sdk-evals-normalizer.ts
  • sdk/src/host-config/templates/seed-host-template.ts
  • sdk/src/host-config/types.ts
  • sdk/src/mcp-client-manager/MCPClientManager.ts
  • sdk/tests/MCPClientManager.auto-protocol-reconnect.test.ts
  • sdk/tests/host-compat-market-hosts.test.ts
  • sdk/tests/host-config-canonicalize.test.ts
  • sdk/tests/host-config-sdk-evals-normalizer.test.ts
  • sdk/tests/host-connection.test.ts
  • sdk/tests/host.test.ts
  • sdk/tests/support/dual-era-fixture.test.ts

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Internal preview

Preview URL: https://mcp-inspector-pr-3828.up.railway.app
Deployed commit: fe1d6c1
PR head commit: 6210914
Backend target: staging fallback.
Health: ✅ Convex reachable
Access is employee-only in non-production environments.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 24 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx Outdated
Comment thread sdk/tests/support/dual-era-fixture.test.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx (2)

867-867: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

State the per-server override rule in the tooltip.

A host pin does not apply to every server. A concrete per-server protocol override takes precedence.

- title="Automatic: negotiate at connect time. Any other choice pins that exact revision for every server on this client."
+ title="Automatic: negotiate at connect time. Any other choice pins that exact revision unless a server has its own protocol override."
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx`
at line 867, Update the tooltip text for the protocol selection control to
clarify that the host-level pin applies by default, but a concrete per-server
protocol override takes precedence and can select a different revision for that
server.

616-627: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Preserve complete initialize.clientInfo data during JSON edits.

protocolToJson emits only name and version. This code then replaces initialize with that reduced object. An unrelated JSON edit deletes clientInfo fields such as title and future-spec fields that the profile type and canonicalizer support.

Serialize and parse the full clientInfo record, while validating name and version.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx`
around lines 616 - 627, Update protocolToJson’s initialize handling to preserve
the complete initialize.clientInfo record by serializing and parsing all
clientInfo fields, rather than constructing an object containing only name and
version. Validate the required name and version values during parsing, then use
the preserved full record when assigning initialize.clientInfo in the next
HostConfigMcpProfileV1 object.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx`:
- Line 867: Update the tooltip text for the protocol selection control to
clarify that the host-level pin applies by default, but a concrete per-server
protocol override takes precedence and can select a different revision for that
server.
- Around line 616-627: Update protocolToJson’s initialize handling to preserve
the complete initialize.clientInfo record by serializing and parsing all
clientInfo fields, rather than constructing an object containing only name and
version. Validate the required name and version values during parsing, then use
the preserved full record when assigning initialize.clientInfo in the next
HostConfigMcpProfileV1 object.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ee5847c8-a84c-45a7-b4c5-05ef98bf1241

📥 Commits

Reviewing files that changed from the base of the PR and between 2b185fa and 6210914.

⛔ Files ignored due to path filters (2)
  • sdk/src/host-compat/catalog.generated.ts is excluded by !**/*.generated.*
  • sdk/tests/__snapshots__/host-config-seed-host-template.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (18)
  • mcpjam-inspector/client/src/components/hosts/redesigned/focus/ProtocolTab.tsx
  • mcpjam-inspector/client/src/components/hosts/redesigned/focus/__tests__/ProtocolTab.versionDropdown.test.tsx
  • mcpjam-inspector/client/src/lib/__tests__/client-config-v2-mcp-profile.test.ts
  • mcpjam-inspector/client/src/lib/host-config-field-schema.ts
  • sdk/src/host-config/canonicalize.ts
  • sdk/src/host-config/defaults.ts
  • sdk/src/host-config/host-connection.ts
  • sdk/src/host-config/public-types.ts
  • sdk/src/host-config/templates/seed-host-template.ts
  • sdk/src/host-config/types.ts
  • sdk/src/mcp-client-manager/MCPClientManager.ts
  • sdk/tests/MCPClientManager.auto-protocol-reconnect.test.ts
  • sdk/tests/host-compat-market-hosts.test.ts
  • sdk/tests/host-config-canonicalize.test.ts
  • sdk/tests/host-config-defaults.test.ts
  • sdk/tests/host-connection.test.ts
  • sdk/tests/host.test.ts
  • sdk/tests/support/dual-era-fixture.test.ts
🚧 Files skipped from review as they are similar to previous changes (10)
  • sdk/src/host-config/templates/seed-host-template.ts
  • sdk/tests/host.test.ts
  • sdk/tests/host-compat-market-hosts.test.ts
  • sdk/src/mcp-client-manager/MCPClientManager.ts
  • sdk/src/host-config/defaults.ts
  • sdk/tests/support/dual-era-fixture.test.ts
  • mcpjam-inspector/client/src/components/hosts/redesigned/focus/tests/ProtocolTab.versionDropdown.test.tsx
  • sdk/tests/host-connection.test.ts
  • sdk/tests/MCPClientManager.auto-protocol-reconnect.test.ts
  • sdk/src/host-config/public-types.ts

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 24 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="sdk/tests/host-config-sdk-evals-normalizer.test.ts">

<violation number="1">
P3: The HostJson-projection test dropped its `initialize`/`clientInfo`/`supportedProtocolVersions` assertions entirely rather than migrating them to the new nested `host.mcp.initialize` shape. Since this PR's headline is exactly that these fields now live under `initialize`, the `hostMcpToProfile` path that projects `mcp.initialize` into `mcpProfile.initialize` is left untested — consider replacing the removed setup/assertions with `host.mcp.initialize = { clientInfo: {...}, supportedProtocolVersions: [...] }` and asserting `out.mcpProfile?.initialize` to keep the new behavior covered.</violation>
</file>

<file name="sdk/src/host-config/canonicalize.ts">

<violation number="1">
P3: The new derive block re-implements the exact 5-line sorted-keys reconstruction that already exists in the `initialize` canonicalization just above it (both build a canonical `sortedInit` by iterating `Object.keys(...).sort()`). This is a small but real duplication introduced here; the two blocks can drift if the key-sorting convention ever changes. Extracting the inline sort into a tiny shared helper (e.g. `sortedRecord<T>(input)`) and reusing it in both places keeps the canonicalization path consistent and easier to audit for hash stability.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@@ -694,12 +694,15 @@ function canonicalizeMcpProfile(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new derive block re-implements the exact 5-line sorted-keys reconstruction that already exists in the initialize canonicalization just above it (both build a canonical sortedInit by iterating Object.keys(...).sort()). This is a small but real duplication introduced here; the two blocks can drift if the key-sorting convention ever changes. Extracting the inline sort into a tiny shared helper (e.g. sortedRecord<T>(input)) and reusing it in both places keeps the canonicalization path consistent and easier to audit for hash stability.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At sdk/src/host-config/canonicalize.ts, line 842:

<comment>The new derive block re-implements the exact 5-line sorted-keys reconstruction that already exists in the `initialize` canonicalization just above it (both build a canonical `sortedInit` by iterating `Object.keys(...).sort()`). This is a small but real duplication introduced here; the two blocks can drift if the key-sorting convention ever changes. Extracting the inline sort into a tiny shared helper (e.g. `sortedRecord<T>(input)`) and reusing it in both places keeps the canonicalization path consistent and easier to audit for hash stability.</comment>

<file context>
@@ -865,71 +820,40 @@ function canonicalizeMcpProfile(
-          )[k];
-        }
-        out.initialize = sortedInit;
+      const sortedInit: NonNullable<HostConfigMcpProfileV1["initialize"]> = {};
+      for (const k of Object.keys(initWithDerived).sort()) {
+        (sortedInit as Record<string, unknown>)[k] = (
</file context>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants